package com.example.selfservicestation.mob

import android.util.Base64
import java.io.ByteArrayOutputStream
import kotlin.experimental.xor


fun ByteArray.base64() : String {
    return Base64.encodeToString(this, Base64.NO_WRAP)
}

private val hexEncodingTable = byteArrayOf(
    '0'.code.toByte(), '1'.code.toByte(), '2'.code.toByte(), '3'.code.toByte(), '4'.code.toByte(), '5'.code.toByte(),
    '6'.code.toByte(),
    '7'.code.toByte(),
    '8'.code.toByte(),
    '9'.code.toByte(),
    'A'.code.toByte(),
    'B'.code.toByte(),
    'C'.code.toByte(),
    'D'.code.toByte(),
    'E'.code.toByte(),
    'F'.code.toByte()
)

fun ByteArray.toHexString(space: Boolean = true) : String {
    val out = ByteArrayOutputStream()
    try {
        for (i in 0 until size) {
            val v: Int = this[i].toInt() and 0xff
            out.write(hexEncodingTable[v ushr 4].toInt())
            out.write(hexEncodingTable[v and 0xf].toInt())
            if (space) {
                out.write(' '.code)
            }
        }
    } catch (e: java.lang.Exception) {
        throw IllegalStateException("exception encoding Hex string: " + e.message, e)
    }
    val bytes = out.toByteArray()
    return String(bytes)
}

const val RADIX_62 = 62

/**
 * 把[from, to) 部分的子数组，转换为以 0-9 a-z A-Z 共 62个字符组成的数字
 *
 * @param from 起始
 * @param to 结束（不包含）
 */
fun ByteArray.to62Num(from: Int, to: Int) : Int {
    var sum = 0
    var scale = 1
    for (i in to - 1 downTo from) {
        sum += from62(this[i]) * scale
        scale *= RADIX_62
    }
    return sum
}

/**
 * 把[from, to) 部分的字节做异或
 */
fun ByteArray.xor(from: Int, to: Int) : Byte {
    var res = this[from]
    for (i in (from + 1) until to) {
        res = res xor this[i]
    }
    return res
}

private fun from62(b: Byte): Int {
    if (b in 0x30..0x39) {
        return b - 0x30
    }
    if (b in 0x61..0x7a) {
        return b - 0x57
    }
    if (b in 0x41..0x5a) {
        return b - 0x1d
    }
    throw IllegalArgumentException("$b is not a num char")
}

/**
 * 计算 [from, to) 部分的字节做 的 CRC16 校验值
 * @return 两字节的校验值
 */
fun ByteArray.crc16(from: Int, to: Int) : ByteArray {
    val value = CRC16.crc16(this, from.coerceAtLeast(0), to.coerceAtMost(size))
    val c1 = (0xff00 and value shr 8).toByte()
    val c2 = (0xff and value).toByte()
    return byteArrayOf(c1, c2)
}
